<template>
  <div class="file-upload">
    <div class="file-upload-container" @click.prevent="handleOnClickBtn" v-bind="$attrs">
      <slot v-if="uploadStatus === 'loading'" name="loading">
        <span>正在上传...</span>
      </slot>
      <slot v-else-if="uploadStatus === 'success'" name="uploaded" :uploadedData="uploadedData">
        <span>上传成功</span>
      </slot>
      <slot v-else default>
        <span class="btn btn-light">点击上传</span>
      </slot>
    </div>
    <input type="file" ref="InputRef" v-show="false" @change="uploadFileChange">
  </div>
</template>

<script lang="ts">
import { defineComponent, ref, PropType, watch } from 'vue'
import request from '@/utils/request'
type UploadStatus = 'ready' | 'loading' | 'success' | 'error'
type ChcekFunction = (file: File) => boolean
export default defineComponent({
  name: 'UploadComp',
  props: {
    action: {
      type: String,
      required: true
    },
    beforeUpload: {
      type: Function as PropType<ChcekFunction>
    },
    isClear: {
      type: Boolean,
      default: false
    },
    uploaded: {
      type: String
    }
  },
  inheritAttrs: false,
  emits: ['file-uploaded', 'file-upload-error', 'updateIsClear'],
  setup (props, context) {
    const InputRef = ref<null | HTMLInputElement>(null)
    const uploadStatus = ref<UploadStatus>(props.uploaded ? 'success' : 'ready')
    const uploadedData = ref(props.uploaded)

    const handleOnClickBtn = () => {
      if (InputRef.value) {
        InputRef.value.click()
      }
    }
    const uploadFileChange = (e: Event) => {
      const currentTarget = e.target as HTMLInputElement
      if (currentTarget.files) {
        const files = Array.from(currentTarget.files)
        if (props.beforeUpload) {
          const result = props.beforeUpload(files[0])
          if (!result) return
        }
        const formData = new FormData()
        formData.append(files[0].name, files[0])
        uploadStatus.value = 'loading'
        request({
          url: props.action,
          method: 'post',
          data: formData,
          headers: {
            'Content-Type': 'multipart/form-data'
          }
        }).then(res => {
          if (InputRef.value) {
            InputRef.value.value = ''
          }
          uploadedData.value = res.data.data.url
          context.emit('file-uploaded', res.data)
          uploadStatus.value = 'success'
        }).catch(error => {
          uploadStatus.value = 'error'
          context.emit('file-upload-error', error)
        })
      }
    }
    watch(() => props.isClear, (newV) => {
      if (newV) {
        uploadStatus.value = 'ready'
        uploadedData.value = ''
        context.emit('updateIsClear', false)
      }
    })
    watch(() => props.uploaded, (newV) => {
      if (newV) {
        uploadedData.value = newV
        uploadStatus.value = 'success'
      }
    })

    return {
      InputRef,
      handleOnClickBtn,
      uploadFileChange,
      uploadStatus,
      uploadedData
    }
  }
})
</script>

<style scoped>

</style>
